/*
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

For example,
Given:
s1 = "aabcc",
s2 = "dbbca",

When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.
*/

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        if (s3.length() != s1.length() + s2.length()) return false;
        vector<vector<bool> > bmatrix(s1.length()+1, vector<bool>(s2.length()+1, false));
        bmatrix[0][0] = true;  // "" and ""
        for (int i = 1; i <= s1.length(); i++) {
            bmatrix[i][0] = (bmatrix[i-1][0] && (s1[i-1] == s3[i-1]));
        }
        for (int j = 1; j <= s2.length(); j++) {
            bmatrix[0][j] = (bmatrix[0][j-1] && (s2[j-1] == s3[j-1]));
        }
        for (int i = 1; i <= s1.length(); i++) {
            for (int j = 1; j <= s2.length(); j++) {
                bmatrix[i][j] = ( (bmatrix[i-1][j] && (s1[i-1]==s3[i+j-1])) ||
                                  (bmatrix[i][j-1] && (s2[j-1]==s3[i+j-1])) );
            }
        }
        return bmatrix[s1.length()][s2.length()];
    }
};

#if 0
// Recursion based solution (timed out)
class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        if (s3.length() != s1.length() + s2.length()) return false;
        return interleaveHelper(s1, s2, s3, 0, 0, 0);
    }
private:
    bool interleaveHelper(string &s1, string &s2, string &s3, int idx1, int idx2, int idx) {
        if (idx == s3.size()) return true;
        if (idx1 == s1.size()) { // only s2 is left
            return (s2.compare(idx2, s2.length()-idx2, s3, idx, s3.length()-idx) == 0);
        } else if (idx2 == s2.size()) { // only s2 is left
            return (s1.compare(idx1, s1.length()-idx1, s3, idx, s3.length()-idx) == 0);
        }
        char c = s3[idx], c1 = s1[idx1], c2=s2[idx2];
        return ( (c == c1 && interleaveHelper(s1, s2, s3, idx1+1, idx2, idx+1)) ||
                 (c == c2 && interleaveHelper(s1, s2, s3, idx1, idx2+1, idx+1)) );
    }
};
#endif
